#!/usr/bin/env python3
"""
模拟 Node Exporter 数据生成器
生成系统监控指标数据，供 Prometheus 抓取
"""

import time
import random
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler
import psutil
import json

class MetricsHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/metrics':
            self.send_response(200)
            self.send_header('Content-type', 'text/plain; version=0.0.4; charset=utf-8')
            self.end_headers()
            
            metrics = self.generate_metrics()
            self.wfile.write(metrics.encode('utf-8'))
        elif self.path == '/':
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            
            html = """
            <html>
            <head><title>Mock Node Exporter</title></head>
            <body>
                <h1>Mock Node Exporter</h1>
                <p>模拟的 Node Exporter 服务</p>
                <p><a href="/metrics">查看指标数据</a></p>
                <p>端口: 9100</p>
            </body>
            </html>
            """
            self.wfile.write(html.encode('utf-8'))
        else:
            self.send_response(404)
            self.end_headers()
    
    def generate_metrics(self):
        """生成 Prometheus 格式的指标数据"""
        timestamp = int(time.time() * 1000)
        
        # 获取真实系统信息
        cpu_percent = psutil.cpu_percent(interval=0.1)
        memory = psutil.virtual_memory()
        disk = psutil.disk_usage('/')
        network = psutil.net_io_counters()
        
        # 添加一些随机波动
        cpu_user = cpu_percent + random.uniform(-5, 5)
        cpu_system = random.uniform(5, 15)
        cpu_idle = 100 - cpu_user - cpu_system
        
        metrics = f"""# HELP node_cpu_seconds_total Seconds the CPUs spent in each mode.
# TYPE node_cpu_seconds_total counter
node_cpu_seconds_total{{cpu="0",mode="idle"}} {cpu_idle * 100 + random.uniform(0, 1000)}
node_cpu_seconds_total{{cpu="0",mode="user"}} {cpu_user * 10 + random.uniform(0, 100)}
node_cpu_seconds_total{{cpu="0",mode="system"}} {cpu_system * 10 + random.uniform(0, 100)}

# HELP node_memory_MemTotal_bytes Memory information field MemTotal_bytes.
# TYPE node_memory_MemTotal_bytes gauge
node_memory_MemTotal_bytes {memory.total}

# HELP node_memory_MemAvailable_bytes Memory information field MemAvailable_bytes.
# TYPE node_memory_MemAvailable_bytes gauge
node_memory_MemAvailable_bytes {memory.available}

# HELP node_memory_MemFree_bytes Memory information field MemFree_bytes.
# TYPE node_memory_MemFree_bytes gauge
node_memory_MemFree_bytes {memory.free}

# HELP node_filesystem_size_bytes Filesystem size in bytes.
# TYPE node_filesystem_size_bytes gauge
node_filesystem_size_bytes{{device="/dev/sda1",fstype="ext4",mountpoint="/"}} {disk.total}

# HELP node_filesystem_avail_bytes Filesystem space available to non-root users in bytes.
# TYPE node_filesystem_avail_bytes gauge
node_filesystem_avail_bytes{{device="/dev/sda1",fstype="ext4",mountpoint="/"}} {disk.free}

# HELP node_network_receive_bytes_total Network device statistic receive_bytes.
# TYPE node_network_receive_bytes_total counter
node_network_receive_bytes_total{{device="eth0"}} {network.bytes_recv}

# HELP node_network_transmit_bytes_total Network device statistic transmit_bytes.
# TYPE node_network_transmit_bytes_total counter
node_network_transmit_bytes_total{{device="eth0"}} {network.bytes_sent}

# HELP node_load1 1m load average.
# TYPE node_load1 gauge
node_load1 {psutil.getloadavg()[0] if hasattr(psutil, 'getloadavg') else random.uniform(0.1, 2.0)}

# HELP node_load5 5m load average.
# TYPE node_load5 gauge
node_load5 {psutil.getloadavg()[1] if hasattr(psutil, 'getloadavg') else random.uniform(0.1, 2.0)}

# HELP node_load15 15m load average.
# TYPE node_load15 gauge
node_load15 {psutil.getloadavg()[2] if hasattr(psutil, 'getloadavg') else random.uniform(0.1, 2.0)}

# HELP up Was the last scrape of the target successful.
# TYPE up gauge
up 1

# HELP node_boot_time_seconds Node boot time, in unixtime.
# TYPE node_boot_time_seconds gauge
node_boot_time_seconds {psutil.boot_time()}

# HELP node_time_seconds System time in seconds since epoch (1970).
# TYPE node_time_seconds gauge
node_time_seconds {time.time()}

# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total {time.time() * random.uniform(0.01, 0.1)}

# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes {random.randint(10000000, 50000000)}

# HELP http_requests_total Total number of HTTP requests.
# TYPE http_requests_total counter
http_requests_total{{method="GET",status="200"}} {random.randint(1000, 5000)}
http_requests_total{{method="GET",status="404"}} {random.randint(10, 100)}
http_requests_total{{method="GET",status="500"}} {random.randint(1, 20)}
http_requests_total{{method="POST",status="200"}} {random.randint(500, 2000)}
http_requests_total{{method="POST",status="400"}} {random.randint(5, 50)}

# HELP http_request_duration_seconds HTTP request duration in seconds.
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{{le="0.1"}} {random.randint(800, 900)}
http_request_duration_seconds_bucket{{le="0.5"}} {random.randint(950, 980)}
http_request_duration_seconds_bucket{{le="1.0"}} {random.randint(990, 995)}
http_request_duration_seconds_bucket{{le="2.0"}} {random.randint(998, 999)}
http_request_duration_seconds_bucket{{le="+Inf"}} 1000
http_request_duration_seconds_sum {random.uniform(100, 500)}
http_request_duration_seconds_count 1000
"""
        return metrics
    
    def log_message(self, format, *args):
        """禁用默认日志输出"""
        pass

def run_node_exporter():
    """运行模拟的 Node Exporter"""
    server = HTTPServer(('0.0.0.0', 9100), MetricsHandler)
    print("🚀 Mock Node Exporter 启动成功，监听端口 9100")
    print("📊 指标端点: http://localhost:9100/metrics")
    server.serve_forever()

if __name__ == '__main__':
    run_node_exporter()